import type { Annotation, Point, AnnotationType, EditorState } from '@/types/screenshot'
import { drawAnnotation } from './annotationTools'
import { COLORS, LINE_WIDTHS } from '@/types/screenshot'

/**
 * 画布编辑器类
 */
export class CanvasEditor {
  private canvas: HTMLCanvasElement
  private ctx: CanvasRenderingContext2D
  private backgroundImage: HTMLImageElement | null = null
  private state: EditorState
  private history: Annotation[][] = []
  private historyIndex: number = -1
  private tempAnnotation: Annotation | null = null
  private isDragging: boolean = false
  private dragStart: Point | null = null

  constructor(canvas: HTMLCanvasElement) {
    this.canvas = canvas
    const context = canvas.getContext('2d')
    if (!context) {
      throw new Error('无法获取 Canvas 2D 上下文')
    }
    this.ctx = context

    this.state = {
      currentTool: null,
      currentColor: COLORS.RED,
      currentLineWidth: LINE_WIDTHS.MEDIUM,
      currentFontSize: 16,
      annotations: [],
      selectedAnnotationId: null,
      isDrawing: false,
      numberCount: 0,
    }

    this.setupEventListeners()
  }

  /**
   * 设置背景图片
   */
  setBackgroundImage(imageDataUrl: string): Promise<void> {
    return new Promise((resolve, reject) => {
      const img = new Image()
      img.onload = () => {
        this.backgroundImage = img
        this.canvas.width = img.width
        this.canvas.height = img.height
        this.render()
        resolve()
      }
      img.onerror = reject
      img.src = imageDataUrl
    })
  }

  /**
   * 设置当前工具
   */
  setTool(tool: AnnotationType | null) {
    this.state.currentTool = tool
    this.state.isDrawing = false
  }

  /**
   * 设置颜色
   */
  setColor(color: string) {
    this.state.currentColor = color
  }

  /**
   * 设置线条宽度
   */
  setLineWidth(width: number) {
    this.state.currentLineWidth = width
  }

  /**
   * 设置字体大小
   */
  setFontSize(size: number) {
    this.state.currentFontSize = size
  }

  /**
   * 获取当前状态
   */
  getState(): EditorState {
    return { ...this.state }
  }

  /**
   * 添加标注到历史记录
   */
  private saveToHistory() {
    // 移除当前位置之后的历史记录
    this.history = this.history.slice(0, this.historyIndex + 1)
    // 添加当前状态到历史
    this.history.push([...this.state.annotations])
    this.historyIndex++

    // 限制历史记录数量
    if (this.history.length > 50) {
      this.history.shift()
      this.historyIndex--
    }
  }

  /**
   * 撤销
   */
  undo() {
    if (this.historyIndex > 0) {
      this.historyIndex--
      this.state.annotations = [...this.history[this.historyIndex]]
      this.render()
    }
  }

  /**
   * 重做
   */
  redo() {
    if (this.historyIndex < this.history.length - 1) {
      this.historyIndex++
      this.state.annotations = [...this.history[this.historyIndex]]
      this.render()
    }
  }

  /**
   * 是否可以撤销
   */
  canUndo(): boolean {
    return this.historyIndex > 0
  }

  /**
   * 是否可以重做
   */
  canRedo(): boolean {
    return this.historyIndex < this.history.length - 1
  }

  /**
   * 清除所有标注
   */
  clear() {
    this.state.annotations = []
    this.saveToHistory()
    this.render()
  }

  /**
   * 渲染画布
   */
  private render() {
    // 清空画布
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)

    // 绘制背景图片
    if (this.backgroundImage) {
      this.ctx.drawImage(this.backgroundImage, 0, 0)
    }

    // 绘制所有标注
    for (const annotation of this.state.annotations) {
      drawAnnotation(this.ctx, annotation, this.canvas)
    }

    // 绘制临时标注（正在绘制中的）
    if (this.tempAnnotation) {
      drawAnnotation(this.ctx, this.tempAnnotation, this.canvas)
    }
  }

  /**
   * 设置事件监听器
   */
  private setupEventListeners() {
    this.canvas.addEventListener('mousedown', this.handleMouseDown.bind(this))
    this.canvas.addEventListener('mousemove', this.handleMouseMove.bind(this))
    this.canvas.addEventListener('mouseup', this.handleMouseUp.bind(this))
    this.canvas.addEventListener('mouseleave', this.handleMouseLeave.bind(this))
  }

  /**
   * 鼠标按下事件
   */
  private handleMouseDown(e: MouseEvent) {
    if (!this.state.currentTool) return

    const point = this.getMousePosition(e)
    this.state.isDrawing = true
    this.isDragging = true
    this.dragStart = point

    // 创建新的标注
    const baseAnnotation = {
      id: Date.now().toString(),
      type: this.state.currentTool,
      color: this.state.currentColor,
      lineWidth: this.state.currentLineWidth,
      fontSize: this.state.currentFontSize,
      startPoint: point,
    }

    switch (this.state.currentTool) {
      case 'rect':
      case 'arrow':
      case 'mosaic':
      case 'highlight':
        this.tempAnnotation = {
          ...baseAnnotation,
          endPoint: point,
        } as Annotation
        break
      case 'text':
        // 文字需要弹出输入框
        this.handleTextInput(point)
        break
      case 'number':
        this.state.numberCount++
        this.tempAnnotation = {
          ...baseAnnotation,
          number: this.state.numberCount,
          radius: 20,
        } as Annotation
        this.finishDrawing()
        break
      case 'pen':
      case 'eraser':
        this.tempAnnotation = {
          ...baseAnnotation,
          points: [point],
          eraserWidth: this.state.currentLineWidth * 3,
        } as Annotation
        break
    }
  }

  /**
   * 鼠标移动事件
   */
  private handleMouseMove(e: MouseEvent) {
    if (!this.state.isDrawing || !this.tempAnnotation) return

    const point = this.getMousePosition(e)

    switch (this.tempAnnotation.type) {
      case 'rect':
      case 'arrow':
      case 'mosaic':
      case 'highlight':
        this.tempAnnotation.endPoint = point
        break
      case 'pen':
      case 'eraser':
        if (!this.tempAnnotation.points) {
          this.tempAnnotation.points = []
        }
        this.tempAnnotation.points.push(point)
        break
    }

    this.render()
  }

  /**
   * 鼠标抬起事件
   */
  private handleMouseUp(e: MouseEvent) {
    if (!this.state.isDrawing) return

    this.finishDrawing()
  }

  /**
   * 鼠标离开画布事件
   */
  private handleMouseLeave(e: MouseEvent) {
    if (this.state.isDrawing) {
      this.finishDrawing()
    }
  }

  /**
   * 完成绘制
   */
  private finishDrawing() {
    if (this.tempAnnotation && this.tempAnnotation.type !== 'text') {
      this.state.annotations.push(this.tempAnnotation)
      this.saveToHistory()
    }

    this.tempAnnotation = null
    this.state.isDrawing = false
    this.isDragging = false
    this.render()
  }

  /**
   * 处理文字输入
   */
  private handleTextInput(point: Point) {
    const text = prompt('请输入文字：')
    if (text) {
      const annotation: Annotation = {
        id: Date.now().toString(),
        type: 'text',
        color: this.state.currentColor,
        lineWidth: this.state.currentLineWidth,
        fontSize: this.state.currentFontSize,
        startPoint: point,
        text,
      } as Annotation

      this.state.annotations.push(annotation)
      this.saveToHistory()
      this.render()
    }

    this.state.isDrawing = false
    this.tempAnnotation = null
  }

  /**
   * 获取鼠标在画布上的位置
   */
  private getMousePosition(e: MouseEvent): Point {
    const rect = this.canvas.getBoundingClientRect()
    return {
      x: e.clientX - rect.left,
      y: e.clientY - rect.top,
    }
  }

  /**
   * 导出为图片
   */
  exportAsImage(format: string = 'image/png', quality: number = 1.0): string {
    return this.canvas.toDataURL(format, quality)
  }

  /**
   * 销毁编辑器
   */
  destroy() {
    this.canvas.removeEventListener('mousedown', this.handleMouseDown.bind(this))
    this.canvas.removeEventListener('mousemove', this.handleMouseMove.bind(this))
    this.canvas.removeEventListener('mouseup', this.handleMouseUp.bind(this))
    this.canvas.removeEventListener('mouseleave', this.handleMouseLeave.bind(this))
  }
}

